package cn.migu.music.hangupsms.service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Splitter;

import cn.migu.music.cljz.common.ReturnCode;
import cn.migu.music.cljz.common.model.Response;
import cn.migu.music.common.exception.BusinessException;
import cn.migu.music.common.kafka.MiguKafkaTemplate;
import cn.migu.music.common.utils.LogUtils;
import cn.migu.music.hangupsms.cachemanage.RefreshDBLocalCacheControllerDemo;
import cn.migu.music.hangupsms.cachemanage.handler.BusinessDbDataCacheServices;
import cn.migu.music.hangupsms.common.config.HangUpSmsConfig;
import cn.migu.music.hangupsms.common.entity.AddBlackUserReq;
import cn.migu.music.hangupsms.common.entity.BlackUserDetail;
import cn.migu.music.hangupsms.common.entity.BlackUserInfo;
import cn.migu.music.hangupsms.common.entity.ConfigInfo;
import cn.migu.music.hangupsms.common.entity.MsgSendInfoReq;
import cn.migu.music.hangupsms.common.entity.QueryCountReq;
import cn.migu.music.hangupsms.common.entity.SettingResponse;
import cn.migu.music.hangupsms.common.entity.UserSendMsgInfo;
import cn.migu.music.hangupsms.dbcache.BlackUserInfoMapper;
import cn.migu.music.hangupsms.repository.HangupMsgSendUserMapper;
import cn.migu.music.hangupsms.service.sftp.DelBlackUserRedisCacheService;
import lombok.extern.slf4j.Slf4j;

/**
 * @version 1.0 created by duanhao@migu.cn on 2022/3/7 9:53 上午
 */

@RestController
@Slf4j
public class HangUpService {
    @Autowired
    BaseService                               baseService;
    @Autowired
    private BlackUserInfoMapper               blackUserInfoMapper;
    @Autowired
    private HangUpSmsConfig                   hangUpSmsConfig;
    @Autowired
    private RefreshDBLocalCacheControllerDemo refreshDBLocalCacheControllerDemo;
    @Autowired
    private BusinessDbDataCacheServices       businessDbDataCacheServices;
    @Autowired
    private HangupMsgSendUserMapper           hangupMsgSendUserMapper;
    @Autowired
    private MiguKafkaTemplate                 miguKafkaTemplate;
    @Autowired
    private DelBlackUserRedisCacheService     delBlackUserRedisCacheService;
    @Autowired
    private LocalIdService                    localIdService;

    private static final Splitter             SPLITTER = Splitter.on(",");

    /**
     * 查询黑名单用户信息
     * 
     * @param phoneString
     *            手机号
     * @return
     */
    @GetMapping("/hangupsms/blackUser/detailInfo/v1.0")
    SettingResponse<List<BlackUserDetail>> queryBlackUserInfo(@RequestParam("phoneList") String phoneString) {
        List<String> phoneList = SPLITTER.splitToList(phoneString);
        SettingResponse<List<BlackUserDetail>> response = new SettingResponse<>();
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        response.setResultMessage(SettingResponse.SUCCESS_MSG);
        response.setData(new ArrayList<>());
        if (CollectionUtils.isEmpty(phoneList)) {
            return response;
        }
        if (hangUpSmsConfig.getBlackUserQueryMaxNumber() < phoneList.size()) {
            response.setResultCode(SettingResponse.ERROR_CODE);
            response.setResultMessage("批量查询限制" + hangUpSmsConfig.getBlackUserQueryMaxNumber() + "个号码！");
            return response;
        }
        Map<String, BlackUserInfo> infoMap = getExistBlackPhone(phoneList);
        List<BlackUserDetail> blackUserDetailList = new ArrayList<>(phoneList.size());
        for (String phoneNumber : phoneList) {
            BlackUserInfo blackUserInfo = infoMap.get(phoneNumber);
            BlackUserDetail blackUserDetail = new BlackUserDetail();
            blackUserDetail.setApplying(false);
            blackUserDetail.setPhoneNumber(phoneNumber);
            if (blackUserInfo != null) {
                blackUserDetail.setApplyTime(blackUserInfo.getCreatetime());
                blackUserDetail.setApplying(true);
            }
            blackUserDetailList.add(blackUserDetail);
        }
        response.setData(blackUserDetailList);
        return response;
    }

    private Map<String, BlackUserInfo> getExistBlackPhone(List<String> phoneList) {
        Map<String, BlackUserInfo> blackUserInfoMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(phoneList)) {
            List<BlackUserInfo> blackList = blackUserInfoMapper.queryBlackUserInfoList(phoneList);
            for (BlackUserInfo blackUserInfo : blackList) {
                blackUserInfoMap.put(blackUserInfo.getPhonenumber(), blackUserInfo);
            }
        }
        return blackUserInfoMap;
    }

    /**
     * 黑名单用户批量添加
     * 
     * @param phoneString
     *            手机号
     * @return
     */
    @GetMapping("/hangupsms/blackUser/batchAdd/v1.0")
    SettingResponse<List<String>> batchAddBlackUser(@RequestParam("phoneList") String phoneString) {
        List<String> phoneList = SPLITTER.splitToList(phoneString);
        SettingResponse<List<String>> response = new SettingResponse<>();
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        response.setResultMessage(SettingResponse.SUCCESS_MSG);
        response.setData(new ArrayList<>());
        if (CollectionUtils.isEmpty(phoneList)) {
            return response;
        }

        // 校验手机号格式
        checkPhoneList(phoneList);

        if (hangUpSmsConfig.getBlackUserInsertMaxNumber() < phoneList.size()) {
            response.setResultCode(SettingResponse.ERROR_CODE);
            response.setResultMessage("批量更新限制" + hangUpSmsConfig.getBlackUserInsertMaxNumber() + "个号码！");
            return response;
        }
        Map<String, BlackUserInfo> blackUserInfoMap = getExistBlackPhone(phoneList);
        // 去除已经添加过的
        List<BlackUserInfo> blackUserInfoList = new ArrayList<>();
        List<String> blackPhoneList = new ArrayList<>();
        for (String phoneNumber : phoneList) {
            if (blackUserInfoMap.get(phoneNumber) == null) {
                blackPhoneList.add(phoneNumber);
                BlackUserInfo blackUserInfo = new BlackUserInfo();
                blackUserInfo.setPhonenumber(phoneNumber);
                blackUserInfo.setLocalId(localIdService.getLocalIdForHangUpBlackUser(phoneNumber));
                blackUserInfoList.add(blackUserInfo);
            }
        }

        response.setData(blackPhoneList);
        if (CollectionUtils.isEmpty(blackPhoneList)) {
            return response;
        }
        try {
            blackUserInfoMapper.batchInsert(blackUserInfoList);
        } catch (Exception e) {
            LogUtils.error(e, log, "add black user error");
            response.setResultCode(ReturnCode.dataBaseError.getCode());
            response.setResultMessage("failed");
        }
        return response;
    }

    /**
     * 挂机短信黑名单用户添加
     * 
     * @param addBlackUserReq
     *            添加请求
     * @return
     */
    @PostMapping("/hangupsms/blackUser/add/v1.0")
    Response addBlackUser(@RequestBody AddBlackUserReq addBlackUserReq) {
        // 校验手机号格式
        checkPhoneNum(addBlackUserReq.getMsisdn());

        BlackUserInfo black = blackUserInfoMapper.queryBlackUserInfo(addBlackUserReq.getMsisdn());
        if (null != black) {
            return Response.success();
        }
        BlackUserInfo blackUserInfo = new BlackUserInfo();
        blackUserInfo.setPhonenumber(addBlackUserReq.getMsisdn());
        blackUserInfo.setCreatetime(LocalDateTime.now());
        Integer localId = localIdService.getLocalIdForHangUpBlackUser(addBlackUserReq.getMsisdn());
        blackUserInfo.setLocalId(localId);
        blackUserInfoMapper.save(blackUserInfo);
        if (!StringUtils.equals("0", addBlackUserReq.getNeedRefresh())) {
            try {
                Thread.sleep(hangUpSmsConfig.getSleepTimes());
            } catch (InterruptedException e) {
                LogUtils.info(e, log, "休眠异常");
            }
            if (!hangUpSmsConfig.isBlackUserCacheSwitchOn()) {
                refreshDBLocalCacheControllerDemo.refreshSoapAddr();
            }
        }
        return Response.success();
    }

    /**
     * 添加黑名单用户
     * 
     * @param addBlackUserReq
     *            添加请求
     * @return
     */
    @PostMapping("/hangupsms/blackUser/add/v1.1")
    Response addBlackUserwithoutFresh(@RequestBody AddBlackUserReq addBlackUserReq) {
        // 校验手机号格式
        checkPhoneNum(addBlackUserReq.getMsisdn());

        BlackUserInfo blackUserInfo = new BlackUserInfo();
        blackUserInfo.setPhonenumber(addBlackUserReq.getMsisdn());
        blackUserInfo.setCreatetime(LocalDateTime.now());
        Integer localId = localIdService.getLocalIdForHangUpBlackUser(addBlackUserReq.getMsisdn());
        blackUserInfo.setLocalId(localId);
        blackUserInfoMapper.save(blackUserInfo);
        return Response.success();
    }

    /**
     * 删除黑名单用户
     * 
     * @param addBlackUserReq
     *            删除请求
     * @return
     */
    @PostMapping("/hangupsms/blackUser/delete/v1.0")
    Response delBlackUser(@RequestBody AddBlackUserReq addBlackUserReq) {
        Response response = new Response();
        blackUserInfoMapper.deleteBlack(addBlackUserReq.getMsisdn());
        // redis缓存删掉的黑名单手机号
        delBlackUserRedisCacheService.delBlackUserCache(addBlackUserReq.getMsisdn());
        response.setReturnCode("000000");
        response.setDescription("success");
        if (!StringUtils.equals("0", addBlackUserReq.getNeedRefresh())) {
            try {
                Thread.sleep(hangUpSmsConfig.getSleepTimes());
            } catch (InterruptedException e) {
                LogUtils.info(e, log, "休眠异常");
            }
            if (!hangUpSmsConfig.isBlackUserCacheSwitchOn()) {
                refreshDBLocalCacheControllerDemo.refreshSoapAddr();
            }
        }
        return response;
    }

    /**
     * 黑名单用户查询
     * 
     * @param addBlackUserReq
     *            查询请求
     * @return
     */
    @PostMapping("/hangupsms/blackUser/query/v1.0")
    Boolean queryBlackUser(@RequestBody AddBlackUserReq addBlackUserReq) {
        if (StringUtils.equals("0", addBlackUserReq.getNeedRefresh())) {
            return businessDbDataCacheServices.isBlackNum(addBlackUserReq.getMsisdn());
        }
        BlackUserInfo blackUserInfo = blackUserInfoMapper.queryBlackUserInfo(addBlackUserReq.getMsisdn());
        return blackUserInfo != null;
    }

    /**
     * 挂机短信下发详情查询
     * 
     * @param msgSendInfoReq
     *            查询请求
     * @return
     */
    @PostMapping("/hangupsms/sms-sendinfo/display/v1.0")
    SettingResponse<List<UserSendMsgInfo>> querySendMsgUserInfo(@RequestBody MsgSendInfoReq msgSendInfoReq) {

        SettingResponse<List<UserSendMsgInfo>> response = new SettingResponse<>();
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        response.setResultMessage(SettingResponse.SUCCESS_MSG);
        response.setData(new ArrayList<>());
        List<UserSendMsgInfo> userSendMsgInfoList = null;
        if (StringUtils.isBlank(msgSendInfoReq.getStartTime()) && StringUtils.isBlank(msgSendInfoReq.getEndTime())) {
            userSendMsgInfoList = hangupMsgSendUserMapper.pageQuerySendMsgUserInfoWithoutTime(msgSendInfoReq.getPhonenumber(),

                Integer.parseInt(msgSendInfoReq.getLocalId()));
        } else {
            userSendMsgInfoList = hangupMsgSendUserMapper.pageQuerySendMsgUserInfo(msgSendInfoReq.getPhonenumber(),
                Timestamp.valueOf(msgSendInfoReq.getStartTime()), Timestamp.valueOf(msgSendInfoReq.getEndTime()),
                Integer.parseInt(msgSendInfoReq.getLocalId()));
        }

        response.setData(userSendMsgInfoList);
        return response;
    }

    /**
     * 数量统计查询
     * 
     * @param queryCountReq
     *            查询请求
     * @return
     */
    @GetMapping("/hangupsms/count/query/v1.0")
    JSONObject queryCount(QueryCountReq queryCountReq) {
        JSONObject json = new JSONObject();
        json.put("SUMCOUNT", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "SUMCOUNT", queryCountReq.getDate()));
        json.put("INDEX_12", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "INDEX_12", queryCountReq.getDate()));
        json.put("PROVINCE", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "PROVINCE", queryCountReq.getDate()));
        json.put("OUTTIME", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "OUTTIME", queryCountReq.getDate()));
        json.put("BLACK", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "BLACK", queryCountReq.getDate()));
        json.put("INDEXG", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "INDEXG", queryCountReq.getDate()));
        json.put("COUNTLIMIT", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "COUNTLIMIT", queryCountReq.getDate()));
        json.put("NOMOBILE", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "NOMOBILE", queryCountReq.getDate()));
        json.put("CRBTUSER", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "CRBTUSER", queryCountReq.getDate()));
        json.put("CURRENTLIMIT", baseService.queryRedisCountByName(queryCountReq.getProvinceName(), "CURRENTLIMIT", queryCountReq.getDate()));
        return json;
    }

    /**
     * 投递Flink同步配置信息
     * 
     * @return SettingResponse<String>
     */
    @GetMapping("/hangupsms/config/sync/v1.0")
    SettingResponse<String> syncConfig() {
        SettingResponse<String> response = new SettingResponse<>();
        try {
            ConfigInfo configInfo = new ConfigInfo();
            configInfo.setSend(baseService.getSendInfoObj());
            configInfo.setNotSend(baseService.getNotSendInfoObj());
            LogUtils.info(log, "挂机短信同步Flink配置信息：%s", JSON.toJSONString(configInfo));
            miguKafkaTemplate.send(hangUpSmsConfig.getProducerTopic(), JSON.toJSONString(configInfo));
            response.setResultCode("0000");
            response.setResultMessage("success");
        } catch (Exception e) {
            LogUtils.error(e, log, "挂机短信同步Flink配置信息异常");
            response.setResultCode(ReturnCode.unkownError.getCode());
            response.setResultMessage("failed");
        }
        return response;
    }

    private void checkPhoneList(List<String> phoneList) {
        if (CollectionUtils.isNotEmpty(phoneList)) {
            for (String phone : phoneList) {
                checkPhoneNum(phone);
            }
        }
    }

    private void checkPhoneNum(String msisdn) {
        if (StringUtils.length(msisdn) != 11 || !isNumeric(msisdn)) {
            throw BusinessException.newInstance("手机号格式错误");
        }
    }

    private boolean isNumeric(String str) {
        return str.matches("\\d+");
    }

}
